﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using Kaskelot.Services.Model;
using Stockholm.SOA.Kaskelot.WCF.ServiceContracts;
using Stockholm.SOA.Kaskelot.WCF.ServiceImplementation.Mapping;
using Stockholm.SOA.Kaskelot.WCF.Core;
using Stockholm.SOA.Kaskelot.WCF.ServiceImplementation.Repositories;
using System.Data.SqlClient;
using System.Configuration;
using System.Data;
using Stockholm.SOA.Kaskelot.WCF.ServiceImplementation.ErrorHandling;

namespace Stockholm.SOA.Kaskelot.WCF.ServiceImplementation
{
	[ServiceBehavior(Namespace = "http://stockholm.se/SOA/Kaskelot/KaskelotService/1", Name = "KaskelotService")]
    [ServiceError(typeof(ErrorHandler))]
	public class KaskelotService : IKaskelotService
	{
		#region Val
		public DataContracts.Val GetVal(Guid? id)
		{
				KaskelotEntities ctx = new KaskelotEntities();
				if (id.HasValue)
				{
					var val = ctx.Val.FirstOrDefault(v => v.Id == id.Value);

				if (val != null)
						return val.ToMinimalContract();
				}

				return ctx.Val.OrderByDescending(v => v.ValDatum).ThenBy(v => v.Benamning).First().ToMinimalContract();
			}

		public void UpdateVal(DataContracts.Val val)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			Val entity = ctx.Val.FirstOrDefault(v => v.Id == val.Id);
			if (entity != null)
			{
				entity.Update(val);
				ctx.SaveChanges();
			}
		}

		public void CreateVal(DataContracts.Val newVal, Guid previousValId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Val.Add(newVal.ToEntity());
			ctx.SaveChanges();

            SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["KaskelotDb"].ConnectionString);
			con.Open();
			SqlCommand command = new SqlCommand("EXEC dbo.CopyVal '" + previousValId.ToString() + "', '" + newVal.Id + "';", con);
			command.ExecuteNonQuery();
		}

		public IEnumerable<DataContracts.Val> GetAllVal()
		{
			KaskelotEntities ctx = new KaskelotEntities();
			return ctx.Val.ToList().Select(x => x.ToMinimalContract());
		}
		#endregion

		#region Blankett
		public DataContracts.Blankett GetBlankettByName(Guid valId, string blankettName)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Blankett.Where(b => b.Namn == blankettName).FirstOrDefault().ToContract();
		}

		public void CreateBlankettPost(DataContracts.BlankettPost blankettPost)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.BlankettPost.Add(blankettPost.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateBlankettPost(DataContracts.BlankettPost blankettPost)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			BlankettPost entity = ctx.BlankettPost.Where(b => b.Id == blankettPost.Id && b.ValId == blankettPost.ValId).FirstOrDefault();

			var faltData = ctx.FaltData.Where(fd => fd.BlankettPostId == entity.Id && fd.ValId == entity.ValId).ToList();

			foreach (FaltData fd in faltData)
				ctx.FaltData.Remove(fd);

			if (entity != null)
			{
				entity.UpdateEntity(blankettPost);
			}
			ctx.SaveChanges();
		}

		public void DeleteBlankettPost(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			BlankettPost entity = ctx.BlankettPost.Where(b => b.Id == id && b.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				var faltData = ctx.FaltData.Where(fd => fd.BlankettPostId == entity.Id && fd.ValId == entity.ValId).ToList();

				foreach (FaltData fd in faltData)
					ctx.FaltData.Remove(fd);

				ctx.BlankettPost.Remove(entity);
			}
			ctx.SaveChanges();
		}

		public void SetFaltDataForBlankettPost(Guid valId, Guid blankettPostId, IEnumerable<DataContracts.FaltData> nyFaltData)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var v = ctx.FaltData.Where(fd => fd.BlankettPostId == blankettPostId && fd.ValId == valId); // Ta bort alla gamla
			foreach (FaltData fd in v)
			{
				ctx.FaltData.Remove(fd);
			}

			foreach (DataContracts.FaltData fd in nyFaltData)	// Lägg till de nya
			{
				ctx.FaltData.Add(fd.ToEntity());
			}

			ctx.SaveChanges();
		}

		public DataContracts.BlankettPost[] GetInkomnaBlankettPoster(Guid valId, string blankett)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			if (string.IsNullOrEmpty(blankett))
				return ctx.BlankettPost.OrderBy(p => p.Skapad).ToList().Select(p => p.ToContract()).ToArray();
			else
				return ctx.BlankettPost.Where(b => b.Blankett.BlankettTyp == (blankett == "Ansökan" ? 0 : 1)).OrderBy(p => p.Skapad).ToList().Select(p => p.ToContract()).ToArray();
		}

		public DataContracts.BlankettPost GetBlankettPost(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.BlankettPost.FirstOrDefault(p => p.Id == id).ToContract();
		}

		public DataContracts.BlankettPost GetBlankettPostByPerson(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
            var bp = ctx.BlankettPost.Where(p => p.PersonId == id).OrderByDescending(p => p.Skapad).FirstOrDefault();
            if (bp != null)
                return bp.ToContract();

            return null;
		}

		#endregion

		#region Byggnad
		public DataContracts.Byggnad[] GetByggnader(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Byggnad.ToArray().Select<Byggnad, DataContracts.Byggnad>(b => b.ToContract()).ToArray();
		}

		public DataContracts.Byggnad GetByggnad(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Byggnad.Where(b => b.Id == id).FirstOrDefault().ToContract();
		}

		public IEnumerable<DataContracts.ByggnadFull> GetByggnadList(Guid valId, IEnumerable<Guid> idList)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			List<DataContracts.ByggnadFull> result = new List<DataContracts.ByggnadFull>();
			IEnumerable<DataContracts.Byggnad> byggnader = ctx.Byggnad.Where(p => idList.Contains(p.Id)).ToList().Select(p => p.ToContract());

			foreach (DataContracts.Byggnad b in byggnader)
			{
				IEnumerable<DataContracts.Materiel> materiel = ctx.Materiel.Where(m => m.ByggnadId == b.Id).ToList().Select(m => m.ToMinimalContract()).OrderBy(m => m.Beskrivning);
				IEnumerable<DataContracts.Skylt> skyltar = ctx.Skylt.Where(s => s.ByggnadId == b.Id).ToList().Select(s => s.ToMinimalContract()).OrderBy(s => s.Beskrivning);
				IEnumerable<DataContracts.Person> kontaktpersoner = ctx.PersonByggnad.Where(pb => pb.ByggnadId == b.Id).ToList().Select(pb => pb.Person.ToMinimalContract()).OrderBy(p => p.Fornamn);

				var lokalIdList = b.Lokaler.Select(l => l.ValdistriktId).ToList();
				var valdistriktIdList = ctx.Valdistrikt.Where(v => lokalIdList.Contains(v.Id)).Select(v => v.ForsamlingId).ToList();
				var forsamlingar = ctx.Forsamling.Where(f => valdistriktIdList.Contains(f.Id)).ToList();
				var forsamlingarIdList = ctx.Forsamling.Where(f => valdistriktIdList.Contains(f.Id)).Select(f => f.ValkretsId).ToList();
				var valkretsar = ctx.Valkrets.Where(v => forsamlingarIdList.Contains(v.Id)).ToList();

				result.Add(new DataContracts.ByggnadFull
				{
					Andrad = b.Andrad,
					AndradAv = b.AndradAv,
					BesokAdress = b.BesokAdress,
					BesokPostNr = b.BesokPostNr,
					BesokPostOrt = b.BesokPostOrt,
					DocumentFolderId = b.DocumentFolderId,
					Fritext = b.Fritext,
					Id = b.Id,
					Inaktiv = b.Inaktiv,
					InformatorKravs = b.InformatorKravs,
					KanExpandera = b.KanExpandera,
					Koordinater = b.Koordinater,
					LeveransAdress = b.LeveransAdress,
					LeveransPostNr = b.LeveransPostNr,
					LeveransPostOrt = b.LeveransPostOrt,
					Namn = b.Namn,
					Skapad = b.Skapad,
					SkapadAv = b.SkapadAv,
					StadsdelId = b.StadsdelId,
					StadsdelNamn = b.StadsdelNamn,
					TypId = b.TypId,
					TypNamn = b.TypNamn,
					ValId = b.ValId,
					Hemsida = b.Hemsida,
					TelNr = b.TelNr,
					Epost = b.Epost,
					Kontaktpersoner = kontaktpersoner,
					Materiel = materiel,
					Skyltar = skyltar,
					Lokaler = b.Lokaler.OrderBy(l => l.Namn).ToList(),
					ForsamlingNamn = String.Join(", ", forsamlingar.Select(f => f.ToMinimalContract().FullName)),
					ValkretsNamn = String.Join(", ", valkretsar.Select(v => v.ToMinimalContract().FullName))
				});
			}

			return result;
		}

		public void UpdateByggnad(DataContracts.Byggnad byggnad)
		{
			KaskelotContext ctx = new KaskelotContext(byggnad.ValId);
			Byggnad entity = ctx.Byggnad.Where(b => b.Id == byggnad.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(byggnad);
			}
			ctx.SaveChanges();
		}

		public Guid CreateByggnad(DataContracts.Byggnad byggnad)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Byggnad.Add(byggnad.ToEntity());
			ctx.SaveChanges();
			return byggnad.Id;
		}

		public void DeleteByggnad(DataContracts.Byggnad byggnad)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Byggnad.Remove(ctx.Byggnad.Where(b => b.Id == byggnad.Id && b.ValId == byggnad.ValId).FirstOrDefault());
			ctx.SaveChanges();
		}

		public DataContracts.ByggnadHandelseLogg[] GetByggnadHandelseLoggByByggnadId(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.ByggnadHandelseLogg.Where(bhl => bhl.ByggnadId == id).OrderByDescending(bhl => bhl.Datum).ToList().Select(bhl => bhl.ToContract()).ToArray();
		}
		#endregion

		#region ByggnadSearch
		public DataContracts.ByggnadSearchLookupResult GetByggnadSearchLookupData(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			DataContracts.ByggnadSearchLookupResult bslr = new DataContracts.ByggnadSearchLookupResult();

			bslr.Valkretsar = ctx.Valkrets.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Namn).ToArray();
			bslr.Stadsdelar = ctx.Stadsdel.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Namn).ToArray();
			bslr.Forsamlingar = ctx.Forsamling.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Namn).ToArray();
			bslr.ByggnadTyper = ctx.ByggnadTyp.ToArray().Select(b => b.ToMinimalContract()).OrderByDescending(x => x.Namn).ToArray();

			return bslr;
		}

		public DataContracts.ByggnadSearchResult[] SearchByggnader(Guid valId, DataContracts.ByggnadSearchParameters parameters)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			HashSet<DataContracts.ByggnadSearchResult> result = new HashSet<DataContracts.ByggnadSearchResult>();

			if (!parameters.Forsamling.HasValue && !parameters.Valkrets.HasValue)
			{
				#region Byggnader
				IEnumerable<Byggnad> byggnader = ctx.Byggnad.ToList();

				if (!String.IsNullOrEmpty(parameters.NamnPostNr))
				{
					byggnader = byggnader.Where(l =>
						l.Benamning.ToLower().Contains(parameters.NamnPostNr.ToLower()) ||
						l.BesokPostNr != null && l.BesokPostNr.ToLower().Contains(parameters.NamnPostNr.ToLower()) ||
						l.LeveransPostNr != null && l.LeveransPostNr.ToLower().Contains(parameters.NamnPostNr.ToLower()));
				}

				if (!String.IsNullOrEmpty(parameters.Fritext))
				{
					byggnader = byggnader.Where(b => b.Fritext != null && b.Fritext.ToLower().Contains(parameters.Fritext.ToLower()));
				}

				if (parameters.Stadsdel.HasValue)
				{
					byggnader = byggnader.Where(b => b.StadsdelId == parameters.Stadsdel);
				}

				if (parameters.Typ.HasValue)
				{
					byggnader = byggnader.Where(b => b.TypId == parameters.Typ);
				}

				byggnader = byggnader.Where(b => b.Inaktiv == parameters.VisaInaktiva);

				foreach (Byggnad b in byggnader)
				{
					if (result.Where(bsr => bsr.ByggnadId == b.Id).ToArray().Length == 0)
					{
						result.Add(new DataContracts.ByggnadSearchResult()
						{
							ByggnadNamn = b.Benamning,
							ValkretsNamn = "",
							ForsamlingNamn = "",
							StadsdelNamn = b.Stadsdel.Benamning,
							Typ = b.ByggnadTyp.Benamning,
							Status = b.Inaktiv ? "Inaktiv" : "Aktiv",
							ByggnadId = b.Id
						});
					}
				}
				#endregion
			}

			#region Lokaler
			IEnumerable<Lokal> lokaler = ctx.Lokal.ToList();

			if (!String.IsNullOrEmpty(parameters.NamnPostNr))
			{
				lokaler = lokaler.Where(l =>
					l.Byggnad.Benamning.ToLower().Contains(parameters.NamnPostNr.ToLower()) ||
					l.Byggnad.BesokPostNr != null && l.Byggnad.BesokPostNr.ToLower().Replace(" ", String.Empty).StartsWith(parameters.NamnPostNr.ToLower().Replace(" ", String.Empty)) ||
					l.Byggnad.LeveransPostNr != null && l.Byggnad.LeveransPostNr.ToLower().Replace(" ", String.Empty).StartsWith(parameters.NamnPostNr.ToLower().Replace(" ", String.Empty)));
			}

			if (!String.IsNullOrEmpty(parameters.Fritext))
			{
				lokaler = lokaler.Where(l => l.Byggnad.Fritext != null && l.Byggnad.Fritext.ToLower().Contains(parameters.Fritext.ToLower()));
			}

			if (parameters.Stadsdel.HasValue)
			{
				lokaler = lokaler.Where(l => l.Byggnad.StadsdelId == parameters.Stadsdel);
			}

			if (parameters.Typ.HasValue)
			{
				lokaler = lokaler.Where(l => l.Byggnad.TypId == parameters.Typ);
			}

            lokaler = lokaler.Where(l => l.Byggnad.Inaktiv == parameters.VisaInaktiva);

			foreach (Lokal l in lokaler)
			{
				if (result.Where(bsr => bsr.ByggnadId == l.ByggnadId).ToArray().Length == 0)
				{
					result.Add(new DataContracts.ByggnadSearchResult()
					{
						ByggnadNamn = l.Byggnad.Benamning,
						ValkretsNamn = l.Valdistrikt != null ? l.Valdistrikt.Forsamling.Valkrets.ToMinimalContract().FullName : "",
						ForsamlingNamn = l.Valdistrikt != null ? l.Valdistrikt.Forsamling.ToMinimalContract().FullName : "",
						ValdistriktNamn = l.Valdistrikt != null ? l.Valdistrikt.ToMinimalContract().FullName : "",
						StadsdelNamn = l.Byggnad.Stadsdel.Benamning,
						Typ = l.Byggnad.ByggnadTyp.Benamning,
						Status = l.Byggnad.Inaktiv ? "Inaktiv" : "Aktiv",
						ByggnadId = l.Byggnad.Id
					});
				}
				else if (l.Valdistrikt != null)
				{
					var v = result.Where(b => b.ByggnadId == l.ByggnadId).FirstOrDefault();

					if (!String.IsNullOrEmpty(v.ForsamlingNamn))
					{
						string[] delim = { ", " };
						var forsamlingar = v.ForsamlingNamn.Split(delim, StringSplitOptions.None);
						var valkretsar = v.ValkretsNamn.Split(delim, StringSplitOptions.None);
						var valdistrikt = v.ValdistriktNamn.Split(delim, StringSplitOptions.RemoveEmptyEntries);

						if (!valdistrikt.Contains(l.Valdistrikt.ToMinimalContract().FullName))
						{
							v.ValdistriktNamn += delim[0] + l.Valdistrikt.ToMinimalContract().FullName;
						}

						if (!forsamlingar.Contains(l.Valdistrikt.Forsamling.ToMinimalContract().FullName))
						{
							v.ForsamlingNamn += delim[0] + l.Valdistrikt.Forsamling.ToMinimalContract().FullName;
						}

						if (!valkretsar.Contains(l.Valdistrikt.Forsamling.Valkrets.ToMinimalContract().FullName))
						{
							v.ValkretsNamn += delim[0] + l.Valdistrikt.Forsamling.Valkrets.ToMinimalContract().FullName;
						}
					}
					else
					{
						v.ValdistriktNamn = l.Valdistrikt.ToMinimalContract().FullName;
						v.ForsamlingNamn = l.Valdistrikt.Forsamling.ToMinimalContract().FullName;
						v.ValkretsNamn = l.Valdistrikt.Forsamling.Valkrets.ToMinimalContract().FullName;
					}
				}
			}

			if (parameters.Valdistrikt.HasValue)
			{
				HashSet<DataContracts.ByggnadSearchResult> delete = new HashSet<DataContracts.ByggnadSearchResult>();
				var x = result.Where(r => !r.ValdistriktNamn.Contains(ctx.Valdistrikt.Where(f => f.Id == parameters.Valdistrikt.Value).FirstOrDefault().ToMinimalContract().FullName));
				foreach (var item in x)
				{
					delete.Add(item);
				}

				foreach (var item in delete)
				{
					result.Remove(item);
				}
			}
			else if (parameters.Forsamling.HasValue)
			{
				HashSet<DataContracts.ByggnadSearchResult> delete = new HashSet<DataContracts.ByggnadSearchResult>();
				var x = result.Where(r => !r.ForsamlingNamn.Contains(ctx.Forsamling.Where(f => f.Id == parameters.Forsamling.Value).FirstOrDefault().ToMinimalContract().FullName));
				foreach (var item in x)
				{
					delete.Add(item);
				}

				foreach (var item in delete)
				{
					result.Remove(item);
				}
			}
			else if (parameters.Valkrets.HasValue) // Om man redan filtrerat baserat på församling så behöver man inte filtrera på valkrets
			{
				HashSet<DataContracts.ByggnadSearchResult> delete = new HashSet<DataContracts.ByggnadSearchResult>();
				var x = result.Where(r => !r.ValkretsNamn.Contains(ctx.Valkrets.Where(f => f.Id == parameters.Valkrets.Value).FirstOrDefault().ToMinimalContract().FullName));
				foreach (var item in x)
				{
					delete.Add(item);
				}

				foreach (var item in delete)
				{
					result.Remove(item);
				}
			}
			#endregion

			return result.ToArray();
		}
		#endregion

		#region Lokal
		public DataContracts.Lokal GetLokal(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Lokal.Where(l => l.Id == id).FirstOrDefault().ToContract();
		}

		public void UpdateLokal(DataContracts.Lokal lokal)
		{
			KaskelotContext ctx = new KaskelotContext(lokal.ValId);
			Lokal entity = ctx.Lokal.Where(b => b.Id == lokal.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(lokal);
			}
			ctx.SaveChanges();
		}

		public void DeleteLokal(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			Lokal entity = ctx.Lokal.Where(b => b.Id == id && b.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.Lokal.Remove(entity);
			}
			ctx.SaveChanges();
		}

		public void CreateLokal(DataContracts.Lokal lokal)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Lokal.Add(lokal.ToEntity());
			ctx.SaveChanges();
		}

		public DataContracts.GetLokalListByByggnadView[] GetLokalListByByggnad(Guid valId, Guid byggnadId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			IList<DataContracts.GetLokalListByByggnadView> res = new List<DataContracts.GetLokalListByByggnadView>();

			var lokaler = ctx.Lokal.Where(l => l.ByggnadId == byggnadId);

			foreach (Lokal l in lokaler)
			{
				res.Add(
					new DataContracts.GetLokalListByByggnadView
					{
						LokalNamn = l.Benamning,
						LokalId = l.Id.ToString(),
						Status = l.Inaktiv ? "Inaktiv" : "Aktiv",
						ValdistriktNamn = l.Valdistrikt != null ? l.Valdistrikt.ToMinimalContract().FullName : String.Empty,
						ValdistriktId = l.ValdistriktId != null ? l.ValdistriktId.Value.ToString() : String.Empty,
						ForsamlingNamn = l.Valdistrikt != null ? l.Valdistrikt.Forsamling.ToMinimalContract().FullName : String.Empty
					}
				);
			}

			return res.ToArray();
		}
		#endregion

		#region Person
		public DataContracts.Person GetPerson(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Person.Where(p => p.Id == id).ToList().Select(p => p.ToMinimalContract()).FirstOrDefault();
		}

		public DataContracts.Person GetPersonByPersonnummer(Guid valId, string personnummer)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Person.Where(p => p.Personnummer == personnummer).ToList().Select(p => p.ToMinimalContract()).FirstOrDefault();
		}

		public DataContracts.Person GetPersonByEmail(Guid valId, string email)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Person.Where(p => p.Epost == email).ToList().Select(p => p.ToMinimalContract()).FirstOrDefault();
		}

		public void UpdatePerson(DataContracts.Person person)
		{
			KaskelotContext ctx = new KaskelotContext(person.ValId);

			Person entity = ctx.Person.Where(b => b.Id == person.Id).FirstOrDefault();
			if (entity != null)
			{
				person.UpdatePersonPersonTyper(entity, ctx);
				entity.UpdateEntity(person);
			}
			ctx.SaveChanges();
		}

		public Guid CreatePerson(DataContracts.Person personContract)
		{
			Person personEntity = personContract.ToEntity();

			KaskelotEntities ctx = new KaskelotEntities();
			personContract.UpdatePersonPersonTyper(personEntity, ctx);

			ctx.Person.Add(personEntity);
			ctx.SaveChanges();

			return personContract.Id;
		}

		public IEnumerable<DataContracts.PersonFull> GetPersonList(Guid valId, IEnumerable<Guid> idList)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			KaskelotEntities ent = new KaskelotEntities();

			IList<DataContracts.PersonFull> result = new List<DataContracts.PersonFull>();
			IEnumerable<Person> personer = ctx.Person.Where(p => idList.Contains(p.Id)).ToList().OrderBy(p => p.Fornamn).ThenBy(p => p.Efternamn);

			foreach (Person p in personer)
			{
				IEnumerable<DataContracts.BemanningValdistrikt> bemanningvaldistrikt = ent.BemanningValdistrikt.Where(bv => bv.PersonId == p.Id).ToList().Select(bv => bv.ToMinimalContract()).OrderBy(bv => bv.ValDatum);
				IEnumerable<DataContracts.BemanningGrupp> bemanninggrupp = ent.BemanningGrupp.Where(bv => bv.PersonId == p.Id).ToList().Select(bv => bv.ToMinimalContract()).OrderBy(bv => bv.ValDatum);

				DataContracts.Person person = p.ToContract();
				DataContracts.PersonFull pf = new DataContracts.PersonFull();
				pf.Andrad = person.Andrad;
				pf.AndradAv = person.AndradAv;
				pf.AnmalanGodkand = person.AnmalanGodkand;
				pf.AnsokanGodkand = person.AnsokanGodkand;
				pf.Efternamn = person.Efternamn;
				pf.Epost = person.Epost;
				pf.Fornamn = person.Fornamn;
				pf.Fritext = person.Fritext;
				pf.GatuAdress = person.GatuAdress;
				pf.Id = person.Id;
				pf.Inaktiv = person.Inaktiv;
				pf.MobTelNr = person.MobTelNr;
				pf.Personnummer = person.Personnummer;
				pf.PostNr = person.PostNr;
				pf.PostOrt = person.PostOrt;
				pf.Skapad = person.Skapad;
				pf.SkapadAv = person.SkapadAv;
				pf.TelNr = person.TelNr;
				pf.Typer = person.Typer;
				pf.ValId = person.ValId;
				pf.KursTillfalle = p.PersonKursTillfalle.Select(pkt => pkt.KursTillfalle.ToContract()).ToList();
				pf.Uppdrag = bemanningvaldistrikt;
				pf.UppdragGrupp = bemanninggrupp;

				result.Add(pf);
			}

			return result;
		}

		public void CreatePersonPersonTyp(Guid valId, Guid personId, Guid persontypId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			PersonPersonTyp ppt = new PersonPersonTyp()
			{
				Id = Guid.NewGuid(),
				ValId = valId,
				PersonId = personId,
				PersonTypId = persontypId
			};

			ctx.PersonPersonTyp.Add(ppt);
			ctx.SaveChanges();
		}
		#endregion

		#region PersonSearch
		public DataContracts.PersonSearchLookupResult GetPersonSearchLookupData(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			DataContracts.PersonSearchLookupResult pslr = new DataContracts.PersonSearchLookupResult();

			pslr.PersonTyper = ctx.PersonTyp.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Namn).ToArray();
			pslr.Funktioner = ctx.Funktion.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Beskrivning).ToArray();

			return pslr;
		}

		public DataContracts.PersonSearchResult[] SearchPersoner(Guid valId, DataContracts.PersonSearchParameters parameters)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			List<DataContracts.PersonSearchResult> list = new List<DataContracts.PersonSearchResult>();

			var pers = ctx.Person.Select(p => p);

			if (!String.IsNullOrEmpty(parameters.Fritext))
			{
				pers = pers.Where(p => p.Fritext != null && p.Fritext.Contains(parameters.Fritext));
			}

			if (!String.IsNullOrEmpty(parameters.Postnummer))
			{
				pers = pers.Where(p => p != null && p.PostNr.Replace(" ", String.Empty).StartsWith(parameters.Postnummer.Replace(" ", String.Empty)));
			}

			if (!String.IsNullOrEmpty(parameters.Personnummer))
			{
				pers = pers.Where(p => p.Personnummer != null && p.Personnummer.Replace("-", String.Empty).Replace("+", String.Empty).Contains(parameters.Personnummer.Replace("-", String.Empty).Replace("+", String.Empty)));
			}

			if (!String.IsNullOrEmpty(parameters.Namn))
			{
				pers = pers.Where(p => (p.Fornamn.Replace(" ", "") + p.Efternamn.Replace(" ", "")).Contains(parameters.Namn.Replace(" ", "")));
			}

			if (parameters.TypId.HasValue && parameters.TypId != Guid.Empty)
			{
				pers = pers.Where(p => p.PersonPersonTyp.Any(ppt => ppt.PersonTyp.Id == parameters.TypId));
			}

            pers = pers.Where(p => p.Inaktiv == parameters.VisaInaktiva);			

			if (parameters.FunktionId.HasValue)
			{
				pers = pers.Where(p =>
					ctx.BemanningValdistrikt.Where(bv => bv.FunktionId == parameters.FunktionId.Value)
						.Select(bv => bv.PersonId)
						.Contains(p.Id) ||
					ctx.BemanningGrupp.Where(bv => bv.FunktionId == parameters.FunktionId.Value)
						.Select(bv => bv.PersonId)
						.Contains(p.Id));
			}

			if (parameters.EndastBemannade)
			{
				pers = pers.Where(p =>
					ctx.BemanningValdistrikt.Where(bv => bv.TackatJa == true)
						.Select(bv => bv.PersonId)
						.Contains(p.Id) ||
					ctx.BemanningGrupp.Where(bv => bv.TackatJa == true)
						.Select(bv => bv.PersonId)
						.Contains(p.Id));
			}

				KaskelotEntities ent = new KaskelotEntities();

			foreach (Person p in pers)
			{
				HashSet<string> uppdrag = new HashSet<string>();

                if (p.BemanningValdistrikt != null)
				{
                    foreach (BemanningValdistrikt bv in p.BemanningValdistrikt)
					{
						uppdrag.Add(bv.Funktion.Beskrivning);
					}
				}

                if (p.BemanningGrupp != null)
				{
                    foreach (BemanningGrupp bg in p.BemanningGrupp)
					{
						uppdrag.Add(bg.Funktion.Beskrivning);
					}
				}

				string tidigareUppdragString = String.Empty;
				uppdrag.OrderBy(s => s);
				foreach (string s in uppdrag)
				{
					if (!String.IsNullOrEmpty(tidigareUppdragString))
						tidigareUppdragString += " ";

					tidigareUppdragString += s;
				}

                // Använder nytt context för att få med alla val                
                var tidigareUppdragValdistrikt = ent.BemanningValdistrikt.Where(b => b.PersonId == p.Id).OrderByDescending(b => b.Valdistrikt.Forsamling.Valkrets.Val.ValDatum);
                var tidigareUppdragGrupp = ent.BemanningGrupp.Join(ent.Val, g => g.ValId, v => v.Id, (g, v) => new { Grupp = g, Datum = v.ValDatum })
                    .Where(b => b.Grupp.PersonId == p.Id).OrderByDescending(vg => vg.Datum).Select(vg => vg.Grupp);

				IList<DataContracts.BemanningGrupp> uppdragGrupper = new List<DataContracts.BemanningGrupp>();
				foreach (BemanningGrupp g in tidigareUppdragGrupp)
				{
					uppdragGrupper.Add(g.ToMinimalContract());
				}

				IList<DataContracts.BemanningValdistrikt> uppdragValdistrikt = new List<DataContracts.BemanningValdistrikt>();
				foreach (BemanningValdistrikt v in tidigareUppdragValdistrikt)
				{
					uppdragValdistrikt.Add(v.ToMinimalContract());
				}

				list.Add(new DataContracts.PersonSearchResult
				{
					Namn = p.Fornamn + " " + p.Efternamn,
					PersonId = p.Id,
					Personnummer = p.Personnummer,
					Status = p.Inaktiv ? "Inaktiv" : "Aktiv",
					Typer = string.Join(", ", p.PersonPersonTyp.Select(ppt => ppt.PersonTyp.Benamning)),
					Uppdrag = tidigareUppdragString,
					PostNr = p.PostNr,
					PostOrt = p.PostOrt,
					Gatuadress = p.Gatuadress,
					Fritext = p.Fritext != null ? p.Fritext : String.Empty,
					Epost = p.Epost,
					TelNr = p.TelNr,
					MobTelNr = p.MobTelNr,
					UppdragGrupper = uppdragGrupper,
					UppdragValdistrikt = uppdragValdistrikt
				});
			}

			return list.ToArray();
		}
		#endregion

		#region KontaktPerson
		public DataContracts.GetKontaktpersonListByByggnadView[] GetKontaktPersonListByByggnad(Guid valId, Guid byggnadId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			IList<DataContracts.GetKontaktpersonListByByggnadView> result = new List<DataContracts.GetKontaktpersonListByByggnadView>();

			var kontaktpersoner = ctx.PersonByggnad.Where(pb => pb.ByggnadId == byggnadId).Select(pb => pb.PersonId);
			var personer = ctx.Person.Where(p => kontaktpersoner.Contains(p.Id));

			foreach (Person p in personer)
			{
				result.Add(
					new DataContracts.GetKontaktpersonListByByggnadView
					{
						Namn = p.Fornamn + " " + p.Efternamn,
						Epost = p.Epost,
						Telefonnummer = p.TelNr,
						Mobilnummer = p.MobTelNr,
						Id = p.Id.ToString()
					}
				);
			}

			return result.ToArray();
		}

		public void AddKontaktpersonToByggnad(DataContracts.PersonByggnad pb)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.PersonByggnad.Add(pb.ToEntity());
			ctx.SaveChanges();
		}

		public void RemoveKontaktpersonFromByggnad(Guid valId, Guid personId, Guid byggnadId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.PersonByggnad.Remove(ctx.PersonByggnad.Where(pb => pb.PersonId == personId && pb.ByggnadId == byggnadId && pb.ValId == valId).FirstOrDefault());
			ctx.SaveChanges();
		}

		public DataContracts.Byggnad[] GetByggnadListByKontaktpersonId(Guid valId, Guid kontaktpersonId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			var byggnadIdList = ctx.PersonByggnad.Where(pb => pb.PersonId == kontaktpersonId).Select(pb => pb.ByggnadId);
			return ctx.Byggnad.Where(b => byggnadIdList.Contains(b.Id)).ToList().Select(b => b.ToMinimalContract()).ToArray();
		}
		#endregion

		#region ByggnadHändelseLogg
		public DataContracts.ByggnadHandelseLogg[] GetByggnadHandelseLoggTodo(Guid valId)
		{
			List<DataContracts.ByggnadHandelseLogg> todos = new List<DataContracts.ByggnadHandelseLogg>();

			KaskelotContext ctx = new KaskelotContext(valId);

			var result = ctx.ByggnadHandelseLogg.Where(b => b.AtgardKravs == true).ToList();

			foreach (ByggnadHandelseLogg logg in result)
			{
				todos.Add(logg.ToContract());
			}

			return todos.ToArray();
		}

		public DataContracts.ByggnadHandelseLogg GetByggnadHandelseLogg(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.ByggnadHandelseLogg.Where(bhl => bhl.Id == id).FirstOrDefault().ToContract();
		}

		public void UpdateByggnadHandelseLogg(DataContracts.ByggnadHandelseLogg bhl)
		{
			KaskelotContext ctx = new KaskelotContext(bhl.ValId);
			ByggnadHandelseLogg entity = ctx.ByggnadHandelseLogg.Where(b => b.Id == bhl.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(bhl);
			}
			ctx.SaveChanges();
		}

		public void DeleteByggnadHandelseLogg(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ByggnadHandelseLogg entity = ctx.ByggnadHandelseLogg.Where(b => b.Id == id && b.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.ByggnadHandelseLogg.Remove(entity);
			}
			ctx.SaveChanges();
		}

		public void CreateByggnadHandelseLogg(DataContracts.ByggnadHandelseLogg bhl)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.ByggnadHandelseLogg.Add(bhl.ToEntity());
			ctx.SaveChanges();
		}
		#endregion

		#region PersonHändelseLogg
		public DataContracts.PersonHandelseLogg[] GetPersonHandelseLoggTodo(Guid valId)
		{
			List<DataContracts.PersonHandelseLogg> todos = new List<DataContracts.PersonHandelseLogg>();

			KaskelotContext ctx = new KaskelotContext(valId);

			var result = ctx.PersonHandelseLogg.Where(b => b.UppfoljningKravs == true).ToList();

			foreach (PersonHandelseLogg logg in result)
			{
				todos.Add(logg.ToContract());
			}

			return todos.ToArray();
		}

		public DataContracts.PersonHandelseLogg GetPersonHandelseLogg(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.PersonHandelseLogg.Where(bhl => bhl.Id == id).FirstOrDefault().ToContract();
		}

		public void UpdatePersonHandelseLogg(DataContracts.PersonHandelseLogg phl)
		{
			KaskelotContext ctx = new KaskelotContext(phl.ValId);
			PersonHandelseLogg entity = ctx.PersonHandelseLogg.Where(b => b.Id == phl.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(phl);
			}
			ctx.SaveChanges();
		}

		public void CreatePersonHandelseLogg(DataContracts.PersonHandelseLogg phl)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.PersonHandelseLogg.Add(phl.ToEntity());
			ctx.SaveChanges();
		}

		public void DeletePersonHandelseLogg(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			PersonHandelseLogg entity = ctx.PersonHandelseLogg.Where(b => b.Id == id && b.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.PersonHandelseLogg.Remove(entity);
			}
			ctx.SaveChanges();
		}

		public DataContracts.PersonHandelseLogg[] GetPersonHandelseLoggByPersonId(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.PersonHandelseLogg.Where(bhl => bhl.PersonId == id).OrderByDescending(bhl => bhl.Datum).ToList().Select(bhl => bhl.ToContract()).ToArray();
		}
		#endregion

		#region MaterielTyp
		public DataContracts.MaterielTyp[] GetMaterielTypLookupData(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.MaterielTyp.ToArray().Select(mt => mt.ToContract()).ToArray();
		}

		public DataContracts.MaterielTyp[] GetPublicMaterielTypList(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.MaterielTyp.Where(mt => mt.VisaILista == true).ToArray().Select(mt => mt.ToContract()).ToArray();
		}

		public DataContracts.MaterielTyp[] GetMaterielTypList(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.MaterielTyp.ToArray().Select(mt => mt.ToContract()).ToArray();
		}

		public DataContracts.MaterielTyp GetMaterielTyp(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.MaterielTyp.Where(mt => mt.Id == id).ToArray().Select(mt => mt.ToContract()).FirstOrDefault();
		}

		public void CreateMaterielTyp(DataContracts.MaterielTyp mt)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.MaterielTyp.Add(mt.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateMaterielTyp(DataContracts.MaterielTyp mt)
		{
			KaskelotContext ctx = new KaskelotContext(mt.ValId);
			MaterielTyp entity = ctx.MaterielTyp.Where(typ => typ.Id == mt.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(mt);
			}
			ctx.SaveChanges();
		}

		public void DeleteMaterielTyp(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var v = ctx.MaterielTypMaterielTyp.Where(mtmt => mtmt.ParentId == id && mtmt.ValId == valId);
			foreach (MaterielTypMaterielTyp mtmt in v)
			{
				ctx.MaterielTypMaterielTyp.Remove(mtmt);
			}

			ctx.MaterielTyp.Remove(ctx.MaterielTyp.Where(mt => mt.Id == id && mt.ValId == valId).FirstOrDefault());
			ctx.SaveChanges();
		}

		public void SetUnderliggandeMaterielTyperForMaterielTyp(Guid valId, Guid parentId, IEnumerable<DataContracts.MaterielTypMaterielTyp> underliggandeTyper)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var v = ctx.MaterielTypMaterielTyp.Where(mtmt => mtmt.ParentId == parentId && mtmt.ValId == valId); // Ta bort alla gamla typer
			foreach (MaterielTypMaterielTyp mtmt in v)
			{
				ctx.MaterielTypMaterielTyp.Remove(mtmt);
			}

			foreach (DataContracts.MaterielTypMaterielTyp mtmt in underliggandeTyper)	// Lägg till de nya
			{
				ctx.MaterielTypMaterielTyp.Add(mtmt.ToEntity());
			}

			ctx.SaveChanges();
		}

		public DataContracts.MaterielTyp[] GetUnderliggandeMaterielTyperForMaterielTyp(Guid valId, Guid parentId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			var v = ctx.MaterielTypMaterielTyp.Where(mtmt => mtmt.ParentId == parentId).Select(mtmt => mtmt.ChildId);
			var u = ctx.MaterielTyp.Where(mt => v.Contains(mt.Id));
			return u.ToArray().Select(mt => mt.ToContract()).ToArray();
		}
		#endregion

		#region Materiel
		public DataContracts.Materiel GetMateriel(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Materiel.Where(m => m.Id == id).FirstOrDefault().ToContract();
		}

		public void UpdateMateriel(DataContracts.Materiel materiel)
		{
			KaskelotContext ctx = new KaskelotContext(materiel.ValId);
			Materiel entity = ctx.Materiel.Where(m => m.Id == materiel.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(materiel);
			}
			ctx.SaveChanges();
		}

		public void DeleteMateriel(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			Materiel entity = ctx.Materiel.Where(m => m.Id == id && m.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.Materiel.Remove(entity);
			}
			ctx.SaveChanges();
		}

		public void CreateMateriel(DataContracts.Materiel materiel)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Materiel.Add(materiel.ToEntity());
			ctx.SaveChanges();
		}

		public DataContracts.GetMaterielListByByggnadView[] GetMaterielListByByggnad(Guid valId, Guid byggnadId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			IList<DataContracts.GetMaterielListByByggnadView> res = new List<DataContracts.GetMaterielListByByggnadView>();

			var materiel = ctx.Materiel.Where(m => m.ByggnadId == byggnadId);

			foreach (Materiel m in materiel)
			{
				res.Add(
					new DataContracts.GetMaterielListByByggnadView
					{
						Antal = m.Antal,
						Beskrivning = m.MaterielTypId != null ? m.MaterielTyp.Beskrivning : m.Beskrivning,
						MaterielId = m.Id.ToString()
					}
				);
			}

			return res.ToArray();
		}
		#endregion

		#region Skylt
		public DataContracts.Skylt GetSkylt(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Skylt.Where(m => m.Id == id).FirstOrDefault().ToContract();
		}

		public void UpdateSkylt(DataContracts.Skylt skylt)
		{
			KaskelotContext ctx = new KaskelotContext(skylt.ValId);
			Skylt entity = ctx.Skylt.Where(m => m.Id == skylt.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(skylt);
			}
			ctx.SaveChanges();
		}

		public void DeleteSkylt(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			Skylt entity = ctx.Skylt.Where(m => m.Id == id && m.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.Skylt.Remove(entity);
			}
			ctx.SaveChanges();
		}

		public void CreateSkylt(DataContracts.Skylt materiel)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Skylt.Add(materiel.ToEntity());
			ctx.SaveChanges();
		}

		public DataContracts.Skylt[] GetSkyltListByByggnad(Guid valId, Guid byggnadId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Skylt.Where(m => m.ByggnadId == byggnadId).ToArray().Select(m => m.ToContract()).ToArray();
		}
		#endregion

		#region Valkrets
		public DataContracts.Valkrets GetValkrets(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Valkrets.Where(vk => vk.Id == id).ToList().Select(vk => vk.ToContract()).FirstOrDefault();
		}

		public DataContracts.Valkrets[] GetValkretsar(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Valkrets.ToArray().Select(vk => vk.ToContract()).ToArray();
		}

		public void CreateValkrets(DataContracts.Valkrets valkrets)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Valkrets.Add(valkrets.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateValkrets(DataContracts.Valkrets valkrets)
		{
			KaskelotContext ctx = new KaskelotContext(valkrets.ValId);
			Valkrets entity = ctx.Valkrets.Where(vk => vk.Id == valkrets.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(valkrets);
			}
			ctx.SaveChanges();
		}

		public void DeleteValkrets(Guid valId, Guid valkretsId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Valkrets.Remove(ctx.Valkrets.Where(vk => vk.Id == valkretsId && vk.ValId == valId).FirstOrDefault());
			ctx.SaveChanges();
		}
		#endregion

		#region Församling
		public DataContracts.Forsamling GetForsamling(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Forsamling.Where(vk => vk.Id == id).ToList().Select(vk => vk.ToContract()).FirstOrDefault();
		}

		public void CreateForsamling(DataContracts.Forsamling forsamling)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Forsamling.Add(forsamling.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateForsamling(DataContracts.Forsamling forsamling)
		{
			KaskelotContext ctx = new KaskelotContext(forsamling.ValId);
			Forsamling entity = ctx.Forsamling.Where(vk => vk.Id == forsamling.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(forsamling);
			}
			ctx.SaveChanges();
		}

		public void DeleteForsamling(Guid valId, Guid forsamlingId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Forsamling.Remove(ctx.Forsamling.Where(vk => vk.Id == forsamlingId && vk.ValId == valId).FirstOrDefault());
			ctx.SaveChanges();
		}

		public DataContracts.Forsamling[] GetForsamlingar(Guid valId, Guid? valkretsId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			DataContracts.Forsamling[] bslr;
			if (valkretsId != null && valkretsId != Guid.Empty)
				bslr = ctx.Forsamling.Where(f => f.ValkretsId == valkretsId).ToArray().Select(f => f.ToContract()).ToArray();
			else
				bslr = ctx.Forsamling.ToArray().Select(f => f.ToContract()).ToArray();

			return bslr;
		}
		#endregion

		#region Valdistrikt
		public DataContracts.Valdistrikt GetValdistrikt(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Valdistrikt.Where(vk => vk.Id == id).ToList().Select(vk => vk.ToContract()).FirstOrDefault();
		}

		public void CreateValdistrikt(DataContracts.Valdistrikt valdistrikt)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Valdistrikt.Add(valdistrikt.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateValdistrikt(DataContracts.Valdistrikt valdistrikt)
		{
			KaskelotContext ctx = new KaskelotContext(valdistrikt.ValId);
			Valdistrikt entity = ctx.Valdistrikt.Where(vk => vk.Id == valdistrikt.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(valdistrikt);
			}
			ctx.SaveChanges();
		}

		public void DeleteValdistrikt(Guid valId, Guid valdistriktId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var lokaler = ctx.Lokal.Where(l => l.ValdistriktId == valdistriktId && l.ValId == valId);
			foreach (Lokal l in lokaler)
			{
				l.ValdistriktId = null;
			}

			ctx.Valdistrikt.Remove(ctx.Valdistrikt.Where(vk => vk.Id == valdistriktId).FirstOrDefault());
			ctx.SaveChanges();
		}

		public DataContracts.Valdistrikt[] GetValdistriktList(Guid valId, Guid? forsamlingId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			DataContracts.Valdistrikt[] bslr;
			if (forsamlingId != null && forsamlingId != Guid.Empty)
				bslr = ctx.Valdistrikt.Where(vd => vd.ForsamlingId == forsamlingId).ToArray().Select(vd => vd.ToContract()).ToArray();
			else
				bslr = ctx.Valdistrikt.ToArray().Select(vd => vd.ToContract()).ToArray();

			return bslr;
		}
		#endregion

		#region Funktion
		public DataContracts.Funktion GetFunktion(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Funktion.Where(f => f.Id == id).ToList().Select(f => f.ToContract()).FirstOrDefault();
		}

		public DataContracts.Funktion[] GetFunktioner(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Funktion.ToList().Select(f => f.ToContract()).ToArray();
		}

		public void CreateFunktion(DataContracts.Funktion funktion)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Funktion.Add(funktion.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateFunktion(DataContracts.Funktion funktion)
		{
			KaskelotContext ctx = new KaskelotContext(funktion.ValId);
			Funktion entity = ctx.Funktion.Where(f => f.Id == funktion.Id).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(funktion);
			}
			ctx.SaveChanges();
		}

		public void DeleteFunktion(Guid valId, Guid funktionId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Funktion.Remove(ctx.Funktion.Where(f => f.Id == funktionId && f.ValId == valId).FirstOrDefault());
			ctx.SaveChanges();
		}
		#endregion

		#region Vakanser
		public Stockholm.SOA.Kaskelot.WCF.DataContracts.VakansSearchLookupResult GetVakansSearchLookupData(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			DataContracts.VakansSearchLookupResult bvslr = new DataContracts.VakansSearchLookupResult();

			bvslr.Valkretsar = ctx.Valkrets.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Namn).ToArray();
			bvslr.Forsamlingar = ctx.Forsamling.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Namn).ToArray();
			bvslr.Valdistrikt = ctx.Valdistrikt.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Namn).ToArray();
			bvslr.Funktioner = ctx.Funktion.ToArray().Select(b => b.ToMinimalContract()).OrderBy(x => x.Beskrivning).ToArray();

			return bvslr;
		}

		public IEnumerable<Stockholm.SOA.Kaskelot.WCF.DataContracts.VakansSearchResult> VakansSearch(Guid valId, Stockholm.SOA.Kaskelot.WCF.DataContracts.VakansSearchParameters vsp)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			#region BemanningValdistrikt
			var v = ctx.BemanningValdistrikt.Where(bv => !bv.PersonId.HasValue || !bv.TackatJa);

			if (vsp.ValdistriktId.HasValue)
			{
				v = v.Where(x => x.ValdistriktId == vsp.ValdistriktId);
			}
			else if (vsp.ForsamlingId.HasValue)
			{
				var distrikt = ctx.Valdistrikt.Where(vd => vd.ForsamlingId == vsp.ForsamlingId.Value).Select(x => x.Id);
				v = v.Where(x => distrikt.Contains(x.ValdistriktId));
			}
			else if (vsp.ValkretsId.HasValue)
			{
				var forsamlingar = ctx.Forsamling.Where(f => f.ValkretsId == vsp.ValkretsId.Value).Select(x => x.Id);
				var distrikt = ctx.Valdistrikt.Where(vd => forsamlingar.Contains(vd.ForsamlingId)).Select(x => x.Id);
				v = v.Where(x => distrikt.Contains(x.ValdistriktId));
			}

			if (vsp.FunktionId.HasValue)
			{
				v = v.Where(x => x.FunktionId == vsp.FunktionId.Value);
			}
			#endregion
			#region BemanningGrupp
			IQueryable<BemanningGrupp> u = null;
			if (!vsp.ValkretsId.HasValue && !vsp.ForsamlingId.HasValue && !vsp.ValdistriktId.HasValue)
			{
				u = ctx.BemanningGrupp.Where(bg => !bg.PersonId.HasValue || !bg.TackatJa);

				if (vsp.FunktionId.HasValue)
				{
					u = u.Where(x => x.FunktionId == vsp.FunktionId.Value);
				}
			}
			#endregion

			v = v.Take(Constants.MaxSearchResults);
			if (u != null) u = u.Take(Constants.MaxSearchResults - v.Count());

			var result = new List<Stockholm.SOA.Kaskelot.WCF.DataContracts.VakansSearchResult>();

			foreach (BemanningValdistrikt bv in v)
			{
				var distrikt = ctx.Valdistrikt.Where(vd => vd.Id == bv.ValdistriktId).FirstOrDefault();
				var forsamling = ctx.Forsamling.Where(f => f.Id == distrikt.ForsamlingId).FirstOrDefault();
				var krets = ctx.Valkrets.Where(vk => vk.Id == forsamling.ValkretsId).FirstOrDefault();
				var funktion = ctx.Funktion.Where(f => f.Id == bv.FunktionId).FirstOrDefault();

				result.Add(new DataContracts.VakansSearchResult
				{
					ValdistriktId = distrikt.Id.ToString(),
					ValdistriktNamn = distrikt.ToMinimalContract().FullName,
					ForsamlingNamn = forsamling.ToMinimalContract().FullName,
					ValkretsNamn = krets.ToMinimalContract().FullName,
					FunktionNamn = funktion.Beskrivning,
					VakansId = bv.Id.ToString(),
					PersonNamn = bv.Person != null ? bv.Person.Fornamn + " " + bv.Person.Efternamn : String.Empty,
					PersonId = bv.PersonId.ToString(),
					TackatJa = bv.TackatJa.ToString()
				});
			}

			if (u != null)
			{
				foreach (BemanningGrupp bg in u)
				{
					var grupp = ctx.Grupp.Where(g => g.Id == bg.GruppId).FirstOrDefault();
					var funktion = ctx.Funktion.Where(f => f.Id == bg.FunktionId).FirstOrDefault();

					result.Add(new DataContracts.VakansSearchResult
					{
						GruppId = grupp.Id.ToString(),
						GruppNamn = grupp.Benamning,
						FunktionNamn = funktion.Beskrivning,
						VakansId = bg.Id.ToString(),
						PersonNamn = bg.Person != null ? bg.Person.Fornamn + " " + bg.Person.Efternamn : String.Empty,
						PersonId = bg.PersonId.ToString(),
						TackatJa = bg.TackatJa.ToString()
					});
				}
			}

			return result;
		}

		public void BemannaVakans(Guid valId, Guid vakansId, Guid personId, bool removeExisting)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			var distrikt = ctx.BemanningValdistrikt.Where(bv => bv.Id == vakansId).FirstOrDefault();
			var grupp = ctx.BemanningGrupp.Where(bg => bg.Id == vakansId).FirstOrDefault();

			if (distrikt != null)
            {
                if (removeExisting)
                {
                    var existingDistrikt = ctx.BemanningValdistrikt.Where(bv => bv.PersonId == personId);
                    foreach (var d in existingDistrikt)
                    {
                        d.PersonId = null;
						d.TackatJa = false;
						d.MilErsattning = 0;
						d.TaxiUtlagg = 0;
                    }
                }
				distrikt.PersonId = personId;
            }
			else if (grupp != null)
				grupp.PersonId = personId;
			else
				throw new ArgumentException("Vakansen kunde inte hittas.");

			ctx.SaveChanges();
		}
		#endregion

		#region Bemanning: Sökningar
		public IEnumerable<DataContracts.Grupp> GruppSearch(Guid valId, Guid? kursTillfalleId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			var grupper = ctx.Grupp.ToList();

			if (kursTillfalleId.HasValue)
			{
				var kursId = ctx.Kurs.Where(k => k.Id == ctx.KursTillfalle.Where(kt => kt.Id == kursTillfalleId.Value).FirstOrDefault().KursId).FirstOrDefault().Id;
				var kurstillfalleIdList = ctx.KursTillfalle.Where(kt => kt.KursId == kursId).Select(kt => kt.Id);
				var personIKurs = ctx.PersonKursTillfalle.Where(pkt => pkt.PersonId != null && kurstillfalleIdList.Contains(pkt.KursTillfalleId)).Select(pkt => pkt.PersonId);

				grupper = grupper.Where(vd => ctx.BemanningGrupp.Where(bv => bv.PersonId.HasValue && bv.GruppId == vd.Id).Select(bv => bv.PersonId).Any(id => !personIKurs.Contains(id))).ToList();
			}

			return grupper.ToList().Select(g => g.ToContract());
		}

		public IEnumerable<DataContracts.ValdistriktSearchResult> ValdistriktSearch(Guid valId, DataContracts.ValdistriktSearchParameters vsp)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			var valdistrikt = ctx.Valdistrikt.Select(vd => vd);

			if (vsp.KursTillfalleId.HasValue)
			{
				var kursId = ctx.Kurs.Where(k => k.Id == ctx.KursTillfalle.Where(kt => kt.Id == vsp.KursTillfalleId.Value).FirstOrDefault().KursId).FirstOrDefault().Id;
				var kurstillfalleIdList = ctx.KursTillfalle.Where(kt => kt.KursId == kursId).Select(kt => kt.Id);
				var personIKurs = ctx.PersonKursTillfalle.Where(pkt => pkt.PersonId != null && kurstillfalleIdList.Contains(pkt.KursTillfalleId)).Select(pkt => pkt.PersonId);

				valdistrikt = valdistrikt.Where(vd => ctx.BemanningValdistrikt.Where(bv => bv.PersonId.HasValue && bv.ValdistriktId == vd.Id).Select(bv => bv.PersonId).Any(id => !personIKurs.Contains(id)));
			}

			if (vsp.ForsamlingId.HasValue)
			{
				valdistrikt = valdistrikt.Where(vd => vd.ForsamlingId == vsp.ForsamlingId);
			}
			else if (vsp.ValkretsId.HasValue)
			{
				valdistrikt = valdistrikt.Where(vd => vd.Forsamling.ValkretsId == vsp.ValkretsId);
			}

			if (vsp.EndastOkopplade)
			{
				valdistrikt = valdistrikt.Where(vd => !ctx.Lokal.Select(l => l.ValdistriktId).Contains(vd.Id) || vd.Id == vsp.SelectedValdistriktId);
			}

			valdistrikt = valdistrikt.Take(Constants.MaxSearchResults);

			var result = new List<DataContracts.ValdistriktSearchResult>();

			foreach (Valdistrikt vd in valdistrikt)
			{
				var y = ctx.BemanningValdistrikt.Where(bv => bv.ValdistriktId == vd.Id);

				bool s = y.ToList().Count > 0;
				foreach (var z in y)
				{
					if (!z.TackatJa)
					{
						s = false;
						break;
					}
				}

				result.Add(new DataContracts.ValdistriktSearchResult
				{
					ValdistriktId = vd.Id.ToString(),
					ValdistriktNamn = vd.ToMinimalContract().FullName,
					ForsamlingNamn = vd.Forsamling.ToMinimalContract().FullName,
					ValkretsNamn = vd.Forsamling.Valkrets.ToMinimalContract().FullName,
					ValdistriktStatus = s ? "Klar" : "Ej klar"
				});
			}

			return result;
		}

		public IEnumerable<DataContracts.PersonSearchResult> BemanningSearchPersoner(Guid valId, DataContracts.PersonSearchParameters parameters)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			IEnumerable<DataContracts.PersonSearchResult> v = SearchPersoner(valId, parameters);

            if (!parameters.VisaBemannadGrupp && parameters.VisaBemannadValdistrikt)
			{
				var bgpersoner = ctx.BemanningGrupp.Select(bg => bg.PersonId);
                var bvpersoner = ctx.BemanningValdistrikt.Select(bv => bv.PersonId);
                v = v.Where(x => !bgpersoner.Contains(x.PersonId) || bvpersoner.Contains(x.PersonId)).ToList();
			}
            else if (!parameters.VisaBemannadValdistrikt && parameters.VisaBemannadGrupp)
			{
				var bgpersoner = ctx.BemanningGrupp.Select(bg => bg.PersonId);
                var bvpersoner = ctx.BemanningValdistrikt.Select(bv => bv.PersonId);
                v = v.Where(x => !bvpersoner.Contains(x.PersonId) || bgpersoner.Contains(x.PersonId)).ToList();
			}
            else if (!parameters.VisaBemannadValdistrikt && !parameters.VisaBemannadGrupp)
			{
                var bgpersoner = ctx.BemanningGrupp.Select(bg => bg.PersonId);
				var bvpersoner = ctx.BemanningValdistrikt.Select(bv => bv.PersonId);
                v = v.Where(x => !bvpersoner.Contains(x.PersonId) && !bgpersoner.Contains(x.PersonId)).ToList();
			}

			return v.OrderBy(p => p.Namn);
		}

		public IEnumerable<DataContracts.BemanningGrupp> GetBemanningGruppByPersonId(Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.BemanningGrupp.Where(bg => bg.PersonId == id).ToList().Select(bg => bg.ToContract()).ToList();

			foreach (DataContracts.BemanningGrupp bv in v)
			{
				var valet = ctx.Val.Where(val => val.Id == bv.ValId).FirstOrDefault();

				if (valet != null)
				{
					bv.ValNamn = valet.Benamning;

					if (valet.ValDatum.HasValue)
						bv.ValDatum = valet.ValDatum.Value.Year.ToString();
				}
			}

			return v;
		}

		public IEnumerable<DataContracts.BemanningValdistrikt> GetBemanningValdistriktByPersonId(Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.BemanningValdistrikt.Where(bg => bg.PersonId == id).ToList().Select(bg => bg.ToContract()).ToList();

			foreach (DataContracts.BemanningValdistrikt bv in v)
			{
				var valet = ctx.Val.Where(val => val.Id == bv.ValId).FirstOrDefault();

				if (valet != null)
				{
					bv.ValNamn = valet.Benamning;

					if (valet.ValDatum.HasValue)
						bv.ValDatum = valet.ValDatum.Value.Year.ToString();
				}
			}

			return v;
		}
		#endregion

		#region Bemanning: Valdistrikt
		public void RemovePersonFromBemanningValdistrikt(Guid valId, Guid bemanningId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.BemanningValdistrikt.Where(bv => bv.Id == bemanningId && bv.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				v.PersonId = null;
				v.TackatJa = false;
				v.MilErsattning = 0;
				v.TaxiUtlagg = 0;
				ctx.SaveChanges();
			}
		}

		public void DeleteBemanningValdistrikt(Guid valId, Guid bemanningId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.BemanningValdistrikt.Where(bv => bv.Id == bemanningId && bv.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.BemanningValdistrikt.Remove(v);
				ctx.SaveChanges();
			}
		}

		public void CreateBemanningValdistrikt(DataContracts.BemanningValdistrikt bv)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.BemanningValdistrikt.Add(bv.ToEntity());
			ctx.SaveChanges();
		}

		public DataContracts.ValdistriktDetailsView GetValdistriktDetails(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			var lokal = ctx.Lokal.Where(l => l.ValdistriktId == id).FirstOrDefault();
			var distrikt = ctx.Valdistrikt.Where(vd => vd.Id == id).FirstOrDefault();
			var forsamling = ctx.Forsamling.Where(f => f.Id == distrikt.ForsamlingId).FirstOrDefault();
			var valkrets = ctx.Valkrets.Where(vk => vk.Id == forsamling.ValkretsId).FirstOrDefault();

			var bemanning = ctx.BemanningValdistrikt.Where(bvd => bvd.ValdistriktId == id).ToList().Select(bvd => bvd.ToContract()).ToList();

			DataContracts.ValdistriktDetailsView view = new DataContracts.ValdistriktDetailsView
			{
				ValdistriktId = distrikt.Id.ToString(),
				ValdistriktNamn = distrikt.ToMinimalContract().FullName,
				ValdistriktNr = distrikt.ValdistriktNr,
				ForsamlingNamn = forsamling.Benamning,
				ValkretsNamn = valkrets.Benamning,
				LokalNamn = lokal != null ? lokal.Benamning : "Ej vald",
				ByggnadNamn = lokal != null ? lokal.Byggnad.Benamning : "Ej vald",
				ByggnadId = lokal != null ? lokal.ByggnadId.ToString() : String.Empty,
				Anteckning = String.Empty,
				Andrad = distrikt.Andrad.HasValue ? distrikt.Andrad.Value.ToString("yyyy-MM-dd") : string.Empty,
				AndradAv = distrikt.AndradAv,
				Skapad = distrikt.Skapad.ToString("yyyy-MM-dd"),
				SkapadAv = distrikt.SkapadAv,
				BemanningValdistrikt = bemanning
			};

			return view;
		}

		public DataContracts.BemanningValdistrikt GetBemanningValdistrikt(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.BemanningValdistrikt.Where(bv => bv.Id == id).FirstOrDefault().ToContract();
		}

		public void UpdateBemanningValdistrikt(DataContracts.BemanningValdistrikt bg)
		{
			KaskelotContext ctx = new KaskelotContext(bg.ValId);
			var v = ctx.BemanningValdistrikt.Where(bv => bv.Id == bg.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(bg);
				ctx.SaveChanges();
			}
		}

		public IEnumerable<DataContracts.ValdistriktFull> GetValdistriktFull(Guid valId, IEnumerable<Guid> idList)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			List<DataContracts.ValdistriktFull> result = new List<DataContracts.ValdistriktFull>();

			IEnumerable<Valdistrikt> valdistrikt = ctx.Valdistrikt.Where(vd => idList.Contains(vd.Id));

			foreach (Valdistrikt v in valdistrikt)
			{
				DataContracts.ValdistriktFull vf = new DataContracts.ValdistriktFull()
				{
					Id = v.Id,
					Andrad = v.Andrad,
					AndradAv = v.AndradAv,
					Skapad = v.Skapad,
					SkapadAv = v.SkapadAv,
					Forsamling = v.Forsamling.ToContract(),
					ForsamlingNamn = v.Forsamling.Benamning,
					BemanningValdistrikt = v.BemanningValdistrikt.OrderBy(bv => bv.Funktion.Beskrivning).Select(bv => bv.ToContract()).ToList(),
					LokalNamn = v.Lokal.FirstOrDefault() != null ? v.Lokal.FirstOrDefault().Benamning : String.Empty,
					ValkretsNamn = v.Forsamling.Valkrets.Benamning,
					ValId = v.ValId,
					ValdistriktNr = v.ValdistriktNr,
					BemanningKlar = v.BemanningKlar,
					ByggnadNamn = v.Lokal.FirstOrDefault() != null ? v.Lokal.FirstOrDefault().Byggnad.Benamning : String.Empty,
					ByggnadAdress = v.Lokal.FirstOrDefault() != null ? v.Lokal.FirstOrDefault().Byggnad.BesokAdress : String.Empty,
					ByggnadPostNr = v.Lokal.FirstOrDefault() != null ? v.Lokal.FirstOrDefault().Byggnad.BesokPostNr : String.Empty,
					ByggnadPostOrt = v.Lokal.FirstOrDefault() != null ? v.Lokal.FirstOrDefault().Byggnad.BesokPostOrt : String.Empty,
				};

				vf.BemanningValdistrikt.ToList().ForEach(x => x.Person = x.Person ?? new DataContracts.Person());

				result.Add(vf);
			}

			return result;
		}
		#endregion

		#region Bemanning: Grupp
		public void RemovePersonFromBemanningGrupp(Guid valId, Guid bemanningId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			var v = ctx.BemanningGrupp.Where(bv => bv.Id == bemanningId).FirstOrDefault();
			if (v != null)
			{
				v.PersonId = null;
				v.TackatJa = false;
				ctx.SaveChanges();
			}
		}

		public void DeleteBemanningGrupp(Guid valId, Guid bemanningId)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.BemanningGrupp.Where(bv => bv.Id == bemanningId && bv.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.BemanningGrupp.Remove(v);
				ctx.SaveChanges();
			}
		}

		public void CreateBemanningGrupp(DataContracts.BemanningGrupp bv)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.BemanningGrupp.Add(bv.ToEntity());
			ctx.SaveChanges();
		}

		public DataContracts.GruppDetailsView GetGruppDetails(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			var grupp = ctx.Grupp.Where(g => g.Id == id).FirstOrDefault();
			var bemanning = ctx.BemanningGrupp.Where(bvd => bvd.GruppId == id).ToList().Select(bvd => bvd.ToContract()).ToList();

			DataContracts.GruppDetailsView view = new DataContracts.GruppDetailsView
			{
				Anteckning = "",
				BemanningGrupp = bemanning,
				GruppId = grupp.Id.ToString(),
				GruppNamn = grupp.Benamning
			};

			return view;
		}

		public DataContracts.BemanningGrupp GetBemanningGrupp(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.BemanningGrupp.Where(bv => bv.Id == id).FirstOrDefault().ToContract();
		}

		public void UpdateBemanningGrupp(DataContracts.BemanningGrupp bg)
		{
			KaskelotContext ctx = new KaskelotContext(bg.ValId);
			var v = ctx.BemanningGrupp.Where(bv => bv.Id == bg.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(bg);
				ctx.SaveChanges();
			}
		}
		#endregion

		#region Administration: Grupp
		public DataContracts.Grupp GetGrupp(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Grupp.Where(g => g.Id == id).FirstOrDefault().ToContract();
		}

		public void CreateGrupp(DataContracts.Grupp grupp)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Grupp.Add(grupp.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateGrupp(DataContracts.Grupp grupp)
		{
			KaskelotContext ctx = new KaskelotContext(grupp.ValId);
			var v = ctx.Grupp.Where(g => g.Id == grupp.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(grupp);
				ctx.SaveChanges();
			}
		}

		public void DeleteGrupp(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.Grupp.Where(g => g.Id == id && g.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.Grupp.Remove(v);
				ctx.SaveChanges();
			}
		}
		#endregion

		#region Administration: Persontyp
		public IEnumerable<DataContracts.PersonTyp> GetPersonTyper(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.PersonTyp.ToList().Select(pt => pt.ToContract());
		}

		public DataContracts.PersonTyp GetPersonTyp(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.PersonTyp.Where(g => g.Id == id).FirstOrDefault().ToContract();
		}

		public void CreatePersonTyp(DataContracts.PersonTyp personTyp)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.PersonTyp.Add(personTyp.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdatePersonTyp(DataContracts.PersonTyp personTyp)
		{
			KaskelotContext ctx = new KaskelotContext(personTyp.ValId);
			var v = ctx.PersonTyp.Where(g => g.Id == personTyp.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(personTyp);
				ctx.SaveChanges();
			}
		}

		public void DeletePersonTyp(Guid valId, Guid id)
		{
			if (id == DataContracts.PersonTyp.KontaktpersonTypId)
			{
				throw new ApplicationException("Det är ej tillåtet att ta bort typen Kontaktperson");
			}
			else if (id == DataContracts.PersonTyp.RostmottagareTypId)
			{
				throw new ApplicationException("Det är ej tillåtet att ta bort typen Röstmottagare");
			}

			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.PersonTyp.Where(g => g.Id == id && g.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.PersonTyp.Remove(v);
				ctx.SaveChanges();
			}
		}
		#endregion

		#region Administration: Byggnadtyp
		public IEnumerable<DataContracts.ByggnadTyp> GetByggnadTyper(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.ByggnadTyp.ToList().Select(pt => pt.ToContract());
		}

		public DataContracts.ByggnadTyp GetByggnadTyp(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.ByggnadTyp.Where(g => g.Id == id).FirstOrDefault().ToContract();
		}

		public void CreateByggnadTyp(DataContracts.ByggnadTyp ByggnadTyp)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.ByggnadTyp.Add(ByggnadTyp.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateByggnadTyp(DataContracts.ByggnadTyp byggnadTyp)
		{
			KaskelotContext ctx = new KaskelotContext(byggnadTyp.ValId);
			var v = ctx.ByggnadTyp.Where(g => g.Id == byggnadTyp.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(byggnadTyp);
				ctx.SaveChanges();
			}
		}

		public void DeleteByggnadTyp(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.ByggnadTyp.Where(g => g.Id == id && g.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.ByggnadTyp.Remove(v);
				ctx.SaveChanges();
			}
		}
		#endregion

		#region Administration: Stadsdel
		public IEnumerable<DataContracts.Stadsdel> GetStadsdelar(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Stadsdel.ToList().Select(pt => pt.ToContract());
		}

		public DataContracts.Stadsdel GetStadsdel(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Stadsdel.Where(s => s.Id == id).FirstOrDefault().ToContract();
		}

		public void CreateStadsdel(DataContracts.Stadsdel stadsdel)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Stadsdel.Add(stadsdel.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateStadsdel(DataContracts.Stadsdel stadsdel)
		{
			KaskelotContext ctx = new KaskelotContext(stadsdel.ValId);
			var v = ctx.Stadsdel.Where(g => g.Id == stadsdel.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(stadsdel);
				ctx.SaveChanges();
			}
		}

		public void DeleteStadsdel(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.Stadsdel.Where(g => g.Id == id && g.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.Stadsdel.Remove(v);
				ctx.SaveChanges();
			}
		}
		#endregion

		#region Administration: Blankett
		public IEnumerable<DataContracts.Blankett> GetBlanketter(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Blankett.ToList().Select(pt => pt.ToContract());
		}

		public DataContracts.Blankett GetBlankett(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Blankett.Where(g => g.Id == id).FirstOrDefault().ToContract();
		}

		public void CreateBlankett(DataContracts.Blankett blankett)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Blankett.Add(blankett.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateBlankett(DataContracts.Blankett blankett)
		{
			KaskelotContext ctx = new KaskelotContext(blankett.ValId);
			var v = ctx.Blankett.Where(g => g.Id == blankett.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(blankett);
				ctx.SaveChanges();
			}
		}

		public void DeleteBlankett(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.Blankett.Where(g => g.Id == id && g.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.Blankett.Remove(v);
				ctx.SaveChanges();
			}
		}

		public void SetFaltForBlankett(Guid valId, Guid blankettId, IEnumerable<DataContracts.BlankettFalt> aktivaBlankettFalt)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var v = ctx.BlankettFalt.Where(blankettFalt => blankettFalt.BlankettId == blankettId && blankettFalt.ValId == valId); // Ta bort alla gamla
			foreach (BlankettFalt blankettFalt in v)
			{
				ctx.BlankettFalt.Remove(blankettFalt);
			}

			foreach (DataContracts.BlankettFalt blankettFalt in aktivaBlankettFalt)	// Lägg till de nya
			{
				ctx.BlankettFalt.Add(blankettFalt.ToEntity());
			}

			ctx.SaveChanges();
		}

		public DataContracts.Falt[] GetFaltForBlankett(Guid valId, Guid blankettId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			var falt = ctx.BlankettFalt
						.Where(blankettFalt => blankettFalt.BlankettId == blankettId)
						.OrderBy(bf => bf.RadIndex)
						.Select(blankettFalt => blankettFalt.Falt);

			return falt.ToArray().Select(f => f.ToContract()).ToArray();
		}
		#endregion

		#region Administration: Falt
		public IEnumerable<DataContracts.Falt> GetAllaFalt(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Falt.ToList().Select(pt => pt.ToContract()).OrderBy(pt => pt.Namn);
		}

		public DataContracts.Falt GetFalt(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Falt.Where(g => g.Id == id).FirstOrDefault().ToContract();
		}

		public void CreateFalt(DataContracts.Falt Falt)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Falt.Add(Falt.ToEntity());
			ctx.SaveChanges();
		}

		public void UpdateFalt(DataContracts.Falt falt)
		{
			KaskelotContext ctx = new KaskelotContext(falt.ValId);
			var v = ctx.Falt.Where(g => g.Id == falt.Id).FirstOrDefault();
			if (v != null)
			{
				v.UpdateEntity(falt);
				ctx.SaveChanges();
			}
		}

		public void DeleteFalt(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var v = ctx.Falt.Where(g => g.Id == id && g.ValId == valId).FirstOrDefault();
			if (v != null)
			{
				ctx.Falt.Remove(v);
				ctx.SaveChanges();
			}
		}

		public void SetFaltAlternativForFalt(Guid valId, Guid faltId, IEnumerable<DataContracts.FaltAlternativ> aktivaFaltAlternativ)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var v = ctx.FaltAlternativ.Where(faltAlternativ => faltAlternativ.FaltId == faltId && faltAlternativ.ValId == valId); // Ta bort alla gamla
			foreach (FaltAlternativ faltAlternativ in v)
			{
				ctx.FaltAlternativ.Remove(faltAlternativ);
			}

			foreach (DataContracts.FaltAlternativ faltAlternativ in aktivaFaltAlternativ)	// Lägg till de nya
			{
				ctx.FaltAlternativ.Add(faltAlternativ.ToEntity());
			}

			ctx.SaveChanges();
		}

		public DataContracts.FaltAlternativ[] GetFaltAlternativForFalt(Guid valId, Guid faltId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			var faltAlternativ = ctx.FaltAlternativ.Where(fa => fa.FaltId == faltId);
			return faltAlternativ.ToArray().Select(fa => fa.ToContract()).ToArray();
		}

		#endregion

		#region Analys
		public DataContracts.Analys.QueryResult ExecuteQuery(DataContracts.Analys.Query query, Guid valId)
		{
				using (AnalysRepository rep = new AnalysRepository())
				{
					return rep.ExecuteQuery(query, valId);
				}
			}

		public List<DataContracts.Analys.Entity> GetEntities()
		{
				using (AnalysRepository rep = new AnalysRepository())
				{
					return rep.GetEntities();
				}
			}

		public List<DataContracts.Analys.LookupField> GetLookupInformation()
		{
				using (AnalysRepository rep = new AnalysRepository())
				{
					return rep.GetLookupInfo();
				}
			}

		public List<DataContracts.Analys.Query> GetQueriesByPerson(string loginName)
		{
				using (AnalysRepository rep = new AnalysRepository())
				{
					return rep.GetQueriesByPerson(loginName);
				}
			}

		public void SaveQuery(DataContracts.Analys.Query query, string loginName)
		{
				using (AnalysRepository rep = new AnalysRepository())
				{
					string s = query.Name;
					rep.SaveQuery(query, loginName);
				}
			}

		public DataContracts.Analys.Query GetQueryById(int id)
		{
				using (AnalysRepository rep = new AnalysRepository())
				{
					return rep.GetQueryById(id);
				}
			}

		public void DeleteQuery(int id)
		{
				using (AnalysRepository rep = new AnalysRepository())
				{
					rep.DeleteQuery(id);
				}
			}
		#endregion

		#region Extern web
		public DataContracts.ValdistriktDetailsView GetValdistriktDetailsByPersonId(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			DataContracts.ValdistriktDetailsView result = null;
			var z = ctx.BemanningValdistrikt.Where(bv => bv.PersonId == id).FirstOrDefault();
			if (z != null)
			{
				var v = z.Valdistrikt;
				var u = ctx.BemanningValdistrikt.Where(bv => bv.ValdistriktId == v.Id);

				result = new DataContracts.ValdistriktDetailsView
				{
					BemanningValdistrikt = u.ToList().Select(bv => bv.ToMinimalContract()).ToList(),
					ValdistriktId = v.Id.ToString(),
					ValdistriktNamn = v.ToMinimalContract().FullName,
					ForsamlingNamn = v.Forsamling.Benamning,
					ValkretsNamn = v.Forsamling.Valkrets.Benamning,
					LokalNamn = v.Lokal.FirstOrDefault() != null ? v.Lokal.FirstOrDefault().Benamning : String.Empty,
					ByggnadNamn = v.Lokal.FirstOrDefault() != null ? v.Lokal.FirstOrDefault().Byggnad.Benamning : String.Empty
				};
			}

			return result;
		}

		public DataContracts.GruppDetailsView GetGruppDetailsByPersonId(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			DataContracts.GruppDetailsView result = null;
			var z = ctx.BemanningGrupp.Where(bv => bv.PersonId == id).FirstOrDefault();
			if (z != null)
			{
				var v = z.Grupp;
				var u = ctx.BemanningGrupp.Where(bv => bv.GruppId == v.Id);

				result = new DataContracts.GruppDetailsView
				{
					BemanningGruppView = v.BemanningGrupp.Select(x => new Stockholm.SOA.Kaskelot.WCF.DataContracts.BemanningGruppView()
					{
						PersonId = x.PersonId,
						FunktionNamn = x.Funktion.Beskrivning,
						FunktionFullName = x.Funktion.PublikBeskrivning,
						Epost = x.Person.Epost,
						TelNr = x.Person.TelNr,
						MobTelNr = x.Person.MobTelNr,
						Personnummer = x.Person.Personnummer,
						PersonNamn = x.Person.Fornamn + " " + x.Person.Efternamn
					}).ToList(),
					GruppId = v.Id.ToString(),
					GruppNamn = v.Benamning
				};
			}
			return result;
		}
		#endregion

		#region Kurser
		public DataContracts.Kurs[] GetKurser(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Kurs.ToArray().Select(m => m.ToContract()).ToArray();
		}

		public DataContracts.Kurs GetKurs(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.Kurs.Where(kt => kt.Id == id).ToArray().Select(m => m.ToContract()).FirstOrDefault();
		}

		public void UpdateKurs(DataContracts.Kurs kurs)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var entity = ctx.Kurs.Where(kt => kt.Id == kurs.Id && kt.ValId == kurs.ValId).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(kurs);
				ctx.SaveChanges();
			}
		}

		public void CreateKurs(DataContracts.Kurs kurs)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.Kurs.Add(kurs.ToEntity());
			ctx.SaveChanges();
		}

		public void DeleteKurs(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var entity = ctx.Kurs.Where(kt => kt.Id == id && kt.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.Kurs.Remove(entity);
				ctx.SaveChanges();
			}
		}
		#endregion

		#region KursTillfälle
		public DataContracts.KursTillfalle[] GetKursTillfallenByKursId(Guid valId, Guid? KursId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			if (KursId.HasValue)
				return ctx.KursTillfalle.Where(kt => kt.KursId == KursId).ToArray().Select(m => m.ToContract()).ToArray();
			else
				return ctx.KursTillfalle.ToArray().Select(m => m.ToContract()).ToArray();
		}

		public DataContracts.KursTillfalle GetKurstillfalle(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.KursTillfalle.Where(kt => kt.Id == id).ToArray().Select(m => m.ToContract()).FirstOrDefault();
		}

		public void UpdateKurstillfalle(DataContracts.KursTillfalle kurstillfalle)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var entity = ctx.KursTillfalle.Where(kt => kt.Id == kurstillfalle.Id && kt.ValId == kurstillfalle.ValId).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(kurstillfalle);
				ctx.SaveChanges();
			}
		}

		public void CreateKurstillfalle(DataContracts.KursTillfalle kurstillfalle)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			ctx.KursTillfalle.Add(kurstillfalle.ToEntity());
			ctx.SaveChanges();
		}

		public void DeleteKurstillfalle(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var placeringar = ctx.PersonKursTillfalle.Where(pkt => pkt.KursTillfalleId == id);

			// Ta bort alla kopplingstabeller om de inte är kopplade till någon person
			if (placeringar.Where(pkt => pkt.PersonId != null).Count() <= 0)
			{
				foreach (PersonKursTillfalle pkt in placeringar)
				{
					ctx.PersonKursTillfalle.Remove(pkt);
				}
			}

			var entity = ctx.KursTillfalle.Where(kt => kt.Id == id && kt.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.KursTillfalle.Remove(entity);
				ctx.SaveChanges();
			}
		}

		public IEnumerable<DataContracts.KursTillfalle> GetKursTillfalleByPersonId(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			var pkt = ctx.PersonKursTillfalle.Where(x => x.PersonId == id).Select(x => x.KursTillfalleId);
			return ctx.KursTillfalle.Where(kt => pkt.Contains(kt.Id)).ToArray().Select(kt => kt.ToContract()).ToArray();
		}
		#endregion

		#region PersonKursTillfalle
		public void AddPersonKursTillfalle(Guid valId, Guid kurstillfalleId, int antal, string skapadAv)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			for (int i = 0; i < antal; i++)
			{
				PersonKursTillfalle pkt = new PersonKursTillfalle()
				{
					Id = Guid.NewGuid(),
					ValId = valId,
					KursTillfalleId = kurstillfalleId,
					Skapad = DateTime.Now,
					SkapadAv = skapadAv,
					Status = "Placerad"
				};

				ctx.PersonKursTillfalle.Add(pkt);
			}

			ctx.SaveChanges();
		}

		public DataContracts.PersonKursTillfalle[] GetPersonKursTillfallenByKursTillfalleId(Guid valId, Guid kurstillfalleId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.PersonKursTillfalle.Where(pkt => pkt.KursTillfalleId == kurstillfalleId).ToArray().Select(pkt => pkt.ToMinimalContract()).ToArray();
		}

		public void DeletePersonKursTillfalle(Guid valId, Guid id)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var entity = ctx.PersonKursTillfalle.Where(pkt => pkt.Id == id && pkt.ValId == valId).FirstOrDefault();
			if (entity != null)
			{
				ctx.PersonKursTillfalle.Remove(entity);
				ctx.SaveChanges();
			}
		}

		public DataContracts.PersonKursTillfalle GetPersonKursTillfalle(Guid valId, Guid id)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			return ctx.PersonKursTillfalle.Where(pkt => pkt.Id == id).ToArray().Select(pkt => pkt.ToContract()).FirstOrDefault();
		}

		public void UpdatePersonKursTillfalle(DataContracts.PersonKursTillfalle personkurstillfalle)
		{
			KaskelotEntities ctx = new KaskelotEntities();
			var entity = ctx.PersonKursTillfalle.Where(pkt => pkt.Id == personkurstillfalle.Id && pkt.ValId == personkurstillfalle.ValId).FirstOrDefault();
			if (entity != null)
			{
				entity.UpdateEntity(personkurstillfalle);

				if (entity.PersonId != null)
				{
					var temp = ctx.KursTillfalle.Where(kt => kt.Id == personkurstillfalle.KursTillfalleId).FirstOrDefault();
					if (temp != null)
					{

						var v = ctx.PersonKursTillfalle.Where(x => 
							x.ValId == personkurstillfalle.ValId && 
							x.PersonId == personkurstillfalle.PersonId &&
							x.KursTillfalle.KursId == temp.KursId &&
							x.Id != entity.Id && x.Status != "Närvaro").FirstOrDefault();

						if (v != null)
							v.PersonId = null;
					}
				}

				ctx.SaveChanges();
			}
		}

		public void PlaceraValdistriktTillKursTillfalle(Guid valId, Guid valdistriktId, Guid kurstillfalleId)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var personer = ctx.BemanningValdistrikt.Where(bv => bv.ValId == valId && bv.ValdistriktId == valdistriktId && bv.PersonId.HasValue).Select(bv => bv.PersonId.Value).ToArray();
			var kurstillfalle = ctx.KursTillfalle.Where(kt => kt.Id == kurstillfalleId && kt.ValId == valId).FirstOrDefault();

			if (kurstillfalle == null)
				throw new ApplicationException("Kurstillfället kunde inte hittas");

			var ktTillSammaKurs = ctx.KursTillfalle.Where(kt => kt.KursId == kurstillfalle.KursId).Select(kt => kt.Id);
			var pktTillSammaKurs = ctx.PersonKursTillfalle.Where(pkt => ktTillSammaKurs.Contains(pkt.KursTillfalleId)).Select(pkt => pkt.PersonId);

			personer = personer.Where(p => !pktTillSammaKurs.Contains(p)).ToArray();

			var ledigaPlatser = ctx.PersonKursTillfalle.Where(pkt =>
				pkt.ValId == valId &&
				pkt.KursTillfalleId == kurstillfalleId &&
				pkt.PersonId == null
			).ToArray();

			if (personer.Count() > ledigaPlatser.Count())
				personer = personer.Take(ledigaPlatser.Count()).ToArray();

			for (int i = 0; i < personer.Count(); i++)
			{
				PersonKursTillfalle pkt = ledigaPlatser[i];

				if (pkt != null)
				{
					pkt.PersonId = personer[i];
				}
			}

			ctx.SaveChanges();
		}

		public void PlaceraGruppTillKursTillfalle(Guid valId, Guid gruppId, Guid kurstillfalleId)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			var personer = ctx.BemanningGrupp.Where(bv => bv.ValId == valId && bv.GruppId == gruppId && bv.PersonId.HasValue).Select(bv => bv.PersonId.Value).ToArray();
			var kurstillfalle = ctx.KursTillfalle.Where(kt => kt.Id == kurstillfalleId && kt.ValId == valId).FirstOrDefault();

			if (kurstillfalle == null)
				throw new ApplicationException("Kurstillfället kunde inte hittas");

			var ktTillSammaKurs = ctx.KursTillfalle.Where(kt => kt.KursId == kurstillfalle.KursId).Select(kt => kt.Id);
			var pktTillSammaKurs = ctx.PersonKursTillfalle.Where(pkt => ktTillSammaKurs.Contains(pkt.KursTillfalleId)).Select(pkt => pkt.PersonId);

			personer = personer.Where(p => !pktTillSammaKurs.Contains(p)).ToArray();

			var ledigaPlatser = ctx.PersonKursTillfalle.Where(pkt =>
				pkt.ValId == valId &&
				pkt.KursTillfalleId == kurstillfalleId &&
				pkt.PersonId == null
			).ToArray();

			if (personer.Count() > ledigaPlatser.Count())
				personer = personer.Take(ledigaPlatser.Count()).ToArray();

			for (int i = 0; i < personer.Count(); i++)
			{
				PersonKursTillfalle pkt = ledigaPlatser[i];

				if (pkt != null)
				{
					pkt.PersonId = personer[i];
				}
			}

			ctx.SaveChanges();
		}
		#endregion

		#region Integrationer
		/// <summary>
		/// Används vid integrationer för att inaktivera en lista med personer och ta bort dem från bemanningen
		/// </summary>
		/// <param name="valId"></param>
		/// <param name="personer"></param>
		public void UpdatePersonList(Guid valId, IEnumerable<DataContracts.Person> personer)
		{
			KaskelotEntities ctx = new KaskelotEntities();

			foreach (DataContracts.Person person in personer)
			{
				Person p = ctx.Person.Where(x => x.ValId == valId && x.Id == person.Id).FirstOrDefault();

				if (p != null)
				{
					p.UpdateEntity(person);

					ctx.BemanningValdistrikt.Where(bv => bv.PersonId == p.Id).ToList().ForEach(bv => bv.PersonId = null);
					ctx.BemanningGrupp.Where(bv => bv.PersonId == p.Id).ToList().ForEach(bv => bv.PersonId = null);
				}
			}

			ctx.SaveChanges();
		}

		public IList<DataContracts.Person> GetPersonListByPersonnummer(Guid valId, IEnumerable<string> personnummer)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			return ctx.Person.ToList().Where(p => personnummer.Contains(p.Personnummer.ToString())).ToList().Select(p => p.ToMinimalContract()).ToList();
		}

		private IEnumerable<DataContracts.PersonData> GetPersonDataIntern(Guid valId, string[] funktionskoderList, bool grupperaPersoner)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			IList<DataContracts.PersonData> result = new List<DataContracts.PersonData>();

			DateTime valdatum = ctx.Val.First(v => v.Id == valId).ValDatum.Value;

			#region Valdistrikt
			var bemanningall = ctx.BemanningValdistrikt.Where(x => funktionskoderList.Contains(x.Funktion.Beskrivning)).ToList();
			var funktionerall = ctx.Funktion.Where(x => funktionskoderList.Contains(x.Beskrivning)).ToList();
			var ansokanall = ctx.BlankettPost.Where(bp => bp.Blankett.BlankettTyp == 0).ToList();

			var personIdList = bemanningall.Select(bv => bv.PersonId).ToArray();
			var personer = ctx.Person.Where(p => personIdList.Contains(p.Id)).ToList();

			foreach (Person x in personer)
			{
				var bemanning = bemanningall.First(bv => bv.PersonId == x.Id);
				var funktioner = funktionerall.First(f => f.Id == bemanning.FunktionId);
				var ansokan = ansokanall.FirstOrDefault(a => a.PersonId == x.Id);
				IEnumerable<FaltData> faltdata = null;
				if (ansokan != null)
					faltdata = ctx.FaltData.Where(fd => fd.BlankettPostId == ansokan.Id).ToList();

				DataContracts.PersonData pd = new DataContracts.PersonData();
				pd.Personnummer = x.Personnummer;
				pd.Fornamn = x.Fornamn;
				pd.Efternamn = x.Efternamn;
				pd.GatuAdress = x.Gatuadress;
				pd.PostNr = x.PostNr;
				pd.PostOrt = x.PostOrt;
				pd.ValDatum = valdatum;
				pd.Arvode = funktioner.Arvode;
				pd.FunktionsKod = funktioner.Beskrivning;
				pd.MilErsattning = bemanning.MilErsattning.HasValue ? bemanning.MilErsattning.Value : 0;
				pd.TaxiUtlagg = bemanning.TaxiUtlagg.HasValue ? bemanning.TaxiUtlagg.Value : 0;
				pd.ValdistriktNamn = bemanning.Valdistrikt.ValdistriktNr;
				pd.ForsamlingNamn = bemanning.Valdistrikt.Forsamling.Benamning;
				pd.ValkretsNamn = bemanning.Valdistrikt.Forsamling.Valkrets.Benamning;
				pd.Uppdrag = bemanning.Valdistrikt.Forsamling.Benamning + " " + bemanning.Valdistrikt.ValdistriktNr;

				if (ansokan != null)
				{
					var fornamn = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "förnamn");
					var efternamn = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "efternamn");
					var personnummer = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "personnummer");
					var adress = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower().Contains("adress"));
					var postnummer = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "postnummer");
					var postort = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "postort");
					var fritext = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "fritext");

					if (fornamn != null)
						pd.AnsokanPersonFornamn = fornamn.Data;
					if (efternamn != null)
						pd.AnsokanPersonEfternamn = efternamn.Data;
					if (personnummer != null)
						pd.AnsokanPersonNummer = personnummer.Data;
					if (adress != null)
						pd.AnsokanAdress = adress.Data;
					if (postnummer != null && postort != null)
						pd.AnsokanPostAdress = postnummer + " " + postort;
					if (fritext != null)
						pd.AnsokanFritext = fritext.Data;
				}

				result.Add(pd);
			}
			#endregion

			#region Grupper
			var bemanningallgrupper = ctx.BemanningGrupp.Where(x => funktionskoderList.Contains(x.Funktion.Beskrivning)).ToList();
			var funktionskoder = funktionskoderList;
			var personergrupper = ctx.Person.Where(p => ctx.BemanningGrupp.Where(bg => funktionskoder.Contains(bg.Funktion.Beskrivning.Trim())).Select(bv => bv.PersonId).Contains(p.Id)).ToList();

			foreach (Person x in personergrupper)
			{
				var bemanning = bemanningallgrupper.First(bv => bv.PersonId == x.Id);
				var funktion = funktionerall.First(f => f.Id == bemanning.FunktionId);
				var ansokan = ansokanall.FirstOrDefault(a => a.PersonId == x.Id);

				if (grupperaPersoner)
				{
					var previousPerson = result.FirstOrDefault(p => p.Personnummer == x.Personnummer);
					if (previousPerson != null)
					{
						previousPerson.Uppdrag = previousPerson.Uppdrag + ", " + bemanning.Grupp.Benamning;
						continue;
					}
				}

				IEnumerable<FaltData> faltdata = null;
				if (ansokan != null)
					faltdata = ctx.FaltData.Where(fd => fd.BlankettPostId == ansokan.Id).ToList();

				DataContracts.PersonData pd = new DataContracts.PersonData();
				pd.Personnummer = x.Personnummer;
				pd.Fornamn = x.Fornamn;
				pd.Efternamn = x.Efternamn;
				pd.GatuAdress = x.Gatuadress;
				pd.PostNr = x.PostNr;
				pd.PostOrt = x.PostOrt;
				pd.ValDatum = valdatum;
				pd.Arvode = funktion.Arvode;
				pd.FunktionsKod = funktion.Beskrivning;
				pd.ValdistriktNamn = string.Empty;
				pd.ForsamlingNamn = string.Empty;
				pd.ValkretsNamn = string.Empty;
				pd.Uppdrag = bemanning.Grupp.Benamning;

				if (ansokan != null)
				{
					var fornamn = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "förnamn");
					var efternamn = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "efternamn");
					var personnummer = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "personnummer");
					var adress = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower().Contains("adress"));
					var postnummer = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "postnummer");
					var postort = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "postort");
					var fritext = faltdata.FirstOrDefault(fd => fd.Falt.Namn.ToLower() == "fritext");

					if (fornamn != null)
						pd.AnsokanPersonFornamn = fornamn.Data;
					if (efternamn != null)
						pd.AnsokanPersonEfternamn = efternamn.Data;
					if (personnummer != null)
						pd.AnsokanPersonNummer = personnummer.Data;
					if (adress != null)
						pd.AnsokanAdress = adress.Data;
					if (postnummer != null && postort != null)
						pd.AnsokanPostAdress = postnummer + " " + postort;
					if (fritext != null)
						pd.AnsokanFritext = fritext.Data;
				}

				result.Add(pd);
			}
			#endregion

			return result;
		}

		public IEnumerable<DataContracts.PersonData> GetPersonDataIntegration(Guid valId) // För eArkiv
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			return GetPersonDataIntern(valId, ctx.Funktion.Where(x => x.ArkivIntegration == true).Select(x => x.Beskrivning).ToArray(), true);
		}

		public IEnumerable<DataContracts.PersonData> GetPersonData(Guid valId) // För LISA
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			return GetPersonDataIntern(valId, ctx.Funktion.Where(x => x.LISAIntegration == true).Select(x => x.Beskrivning).ToArray(), false);
		}

		public IEnumerable<string> GetPersonnummerList(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			return ctx.Person.Where(p => !string.IsNullOrEmpty(p.Personnummer)).Select(p => p.Personnummer).Distinct().ToList();
		}

		public IEnumerable<DataContracts.Lokal> GetLokalData(Guid valId)
		{
			KaskelotContext ctx = new KaskelotContext(valId);

			var allaLokaler = ctx.Lokal.ToList().Select(l => l.ToContract());
			var result = new List<DataContracts.Lokal>();

			foreach (DataContracts.Lokal l in allaLokaler)
			{
				var v = result.FirstOrDefault(x => x.ByggnadId == l.ByggnadId && x.Namn == l.Namn);
				if (v != null)
				{
					v.ValdistriktNamn += ", " + l.ValdistriktNamn;
				}
				else
				{
					result.Add(l);
				}
			}

			return result;
		}
		#endregion

		#region Utskick (SMS & Epost)
		public DataContracts.NotifieringsResultat SkickaSMS(IEnumerable<string> mottagare, string text)
		{
			NotificationRepository nr = new NotificationRepository();

			return nr.SendSMS(mottagare, text);
		}

		public DataContracts.NotifieringsResultat SkickaEpost(Guid valId, DataContracts.BlankettPost blankettPost, DataContracts.FaltData[] faltData)
		{
			KaskelotContext ctx = new KaskelotContext(valId);
			var blankettNamn = ctx.Blankett.FirstOrDefault(x => x.Id == blankettPost.Blankett.Id).Namn;
			NotificationRepository nr = new NotificationRepository();

			foreach (DataContracts.FaltData fd in faltData)
				fd.Falt = ctx.Falt.FirstOrDefault(x => x.Id == fd.Falt.Id).ToContract();

			return nr.SendEmail(blankettNamn, faltData);
		}
		#endregion
	}
}
